﻿#include "CameraHik.h"
#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
#include <QTimer>
#include <QMutexLocker>
#include <QDebug>
#pragma execution_character_set("utf-8")

void __stdcall CameraHik::ImageCallBackEx(unsigned char *pData,MV_FRAME_OUT_INFO_EX *pFrameInfo, void *pUser){
    if (pFrameInfo == NULL){
        printf("pFrame is NULL\n");
        return;
    }
    auto pCamera = static_cast<CameraBase*>(pUser);
    if(pCamera==nullptr)
        return;
    if(!pCamera->getReceiveStatus())
        return;
    ImageInfo imgInfo={0};
    imgInfo.nWidth = pFrameInfo->nWidth;
    imgInfo.nHeight = pFrameInfo->nHeight;
    imgInfo.pData = pData;
    imgInfo.nDataLen = pFrameInfo->nFrameLen;
    imgInfo.enPixelType = pFrameInfo->enPixelType;
    pCamera->preProcessImage(imgInfo);
}

void __stdcall CameraHik::ExceptionCallBack(unsigned int nMsgType, void* pUser)
{
    if(nMsgType == MV_EXCEPTION_DEV_DISCONNECT){
        printf("MV_EXCEPTION_DEV_DISCONNECT");
    }
    else{
        printf("Unknown exception 0x[%x] ", nMsgType);
    }
    auto pCamera = static_cast<CameraBase*>(pUser);
    if(pCamera==nullptr)
        return;
    pCamera->setStatus(CS_Unavailable);
    emit pCamera->sigErrorOccured(pCamera->getName(), CEC_Remove);
}

void __stdcall CameraHik::EventCallBack(MV_EVENT_OUT_INFO * pEventInfo, void* pUser)
{
    auto pCamera = static_cast<CameraBase*>(pUser);
    if(pCamera==nullptr)
        return;
    if (pEventInfo){
        int64_t nBlockId = pEventInfo->nBlockIdHigh;
        nBlockId = (nBlockId << 32) + pEventInfo->nBlockIdLow;
        int64_t nTimestamp = pEventInfo->nTimestampHigh;
        nTimestamp = (nTimestamp << 32) + pEventInfo->nTimestampLow;
    }
}

void CameraHik::saveParamToUserSet()
{
    //save params to user set
    setNodeEnum("UserSetSelector", 1);
    execCommand("UserSetSave");
}

CameraHik::CameraHik():CameraBase()
{
    connect(this,&CameraBase::sigErrorOccured,this,[&](const QString &name, CameraErrorCode errCode){
        if(errCode == CEC_Remove){
            reStart();
        }
    });
}

CameraHik::~CameraHik()
{

}

void CameraHik::initialize()
{
    QMutexLocker mutexLocker(&mLock);
    setStatus(CS_Unavailable);
    // Enum device
    MV_CC_DEVICE_INFO_LIST stDeviceList;
    memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
    auto nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);
    if (MV_OK != nRet){
        printf("Enum Devices fail! nRet [0x%x]\n", nRet);
        return ;
    }

    int nIndex = -1;

    for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++){
        MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i];
        if (NULL == pDeviceInfo){
            break;
        }
        mTLayerType = pDeviceInfo->nTLayerType;
        if(pDeviceInfo->nTLayerType==MV_GIGE_DEVICE){
            QString cameraName = QString(reinterpret_cast<char*>(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName));
            if(cameraName== mCamConfig.name){
                nIndex=i;
                break;
            }
        }else if(pDeviceInfo->nTLayerType==MV_USB_DEVICE){
            QString cameraName = QString(reinterpret_cast<char*>(pDeviceInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName));
            if(cameraName== mCamConfig.name){
                nIndex=i;
                break;
            }
        }
    }

    if (nIndex == -1){
        printf("%s unavailable:\n", mCamConfig.name.toStdString().c_str());
        return ;
    }

    // Select device and create handle
    nRet = MV_CC_CreateHandle(&mHandle, stDeviceList.pDeviceInfo[nIndex]);
    if (MV_OK != nRet){
        printf("%s Create Handle fail! nRet [0x%x]\n", mCamConfig.name.toStdString().c_str(),nRet);
        return;
    }
    // Register image callback
    nRet = MV_CC_RegisterImageCallBackEx(mHandle, ImageCallBackEx, this);
    if (MV_OK != nRet){
        printf("%s Register Image CallBack fail! nRet [0x%x]\n", mCamConfig.name.toStdString().c_str(),nRet);
        return;
    }
    setStatus(CS_Closed);
}

void CameraHik::openCamera()
{
    if(mStatus != CS_Closed)
        return;
    // Open device
    auto nRet = MV_CC_OpenDevice(mHandle,MV_ACCESS_Exclusive,0);
    if (MV_OK != nRet){
        printf("%s Open Device fail! nRet [0x%x]\n", mCamConfig.name.toStdString().c_str(), nRet);
        return;
    }
    // Detection network optimal package size(It only works for the GigE camera)
    if (mTLayerType == MV_GIGE_DEVICE){
        int nPacketSize = MV_CC_GetOptimalPacketSize(mHandle);
        if (nPacketSize > 0){
            setNodeInt("GevSCPSPacketSize",nPacketSize);
        }else{
            printf("%s Warning: Get Packet Size fail nRet [0x%x]!", mCamConfig.name.toStdString().c_str(), nPacketSize);
        }
    }

    // Register disconnected exception callBack
    nRet = MV_CC_RegisterExceptionCallBack(mHandle, ExceptionCallBack, this);
    if (MV_OK != nRet){
        printf("%s RegisterExceptionCallBack fail! nRet [0x%x]\n", mCamConfig.name.toStdString().c_str(), nRet);
        return;
    }
    mCamConfig.isColor = isColor(getNodeEnum("PixelFormat"));
    mCamConfig.isLine = getNodeEnum("DeviceScanType") == 1;
    setStatus(CS_Opened);
}

void CameraHik::startGrabbing()
{
    if(mStatus == CS_Opened){
        int nRet;
        // Start grab image
        nRet = MV_CC_StartGrabbing(mHandle);
        if (MV_OK != nRet){
            printf("%s Start Grabbing fail! nRet [0x%x]\n", mCamConfig.name.toStdString().c_str(), nRet);
            return;
        }
        setStatus(CS_Grabbing);
    }
}

void CameraHik::stopGrabbing()
{
    // Stop grab image
    if(mStatus == CS_Grabbing){
        auto nRet = MV_CC_StopGrabbing(mHandle);
        if (MV_OK != nRet){
            printf("%s Stop Grabbing fail! nRet [0x%x]\n", mCamConfig.name.toStdString().c_str(), nRet);
            return;
        }
        setStatus(CS_Opened);
    }
}

void CameraHik::closeCamera()
{
    if(mStatus == CS_Opened){
        setStatus(CS_Closing);
        // Close device
        auto nRet = MV_CC_CloseDevice(mHandle);
        if (MV_OK != nRet){
            printf("%s Close Device fail! nRet [0x%x]\n", mCamConfig.name.toStdString().c_str(), nRet);
            return;
        }
        setStatus(CS_Closed);
    }
}

void CameraHik::releaseCamera()
{
    // Destroy handle
    if(mHandle){
        auto nRet = MV_CC_DestroyHandle(mHandle);
        if (MV_OK != nRet){
            printf("%s Destroy Handle fail! nRet [0x%x]\n", mCamConfig.name.toStdString().data(), nRet);
        }
    }
    mHandle = nullptr;
    setStatus(CS_Unavailable);
}



void CameraHik::preProcessImage(const ImageInfo &imgInfo)
{
    if(imgInfo.pData == nullptr || mStatus != CS_Grabbing){
        return;
    }
    if (isColor((MvGvspPixelType)imgInfo.enPixelType)){
        unsigned char *pConvertData = NULL;
        unsigned int nConvertDataSize = 0;
        nConvertDataSize = imgInfo.nWidth * imgInfo.nHeight * 3;
        pConvertData = (unsigned char*)malloc(nConvertDataSize);
        if (NULL == pConvertData){
            printf("malloc pConvertData fail!\n");
            return;
        }
        // Convert pixel
        MV_CC_PIXEL_CONVERT_PARAM stConvertParam = {0};

        stConvertParam.nWidth           = imgInfo.nWidth;                 // image width
        stConvertParam.nHeight          = imgInfo.nHeight;               // image height
        stConvertParam.pSrcData         = imgInfo.pData;                         // input data buffer
        stConvertParam.nSrcDataLen      = imgInfo.nDataLen;         // input data size
        stConvertParam.enSrcPixelType   = (MvGvspPixelType)imgInfo.enPixelType;    // input pixel format
        stConvertParam.enDstPixelType   = PixelType_Gvsp_RGB8_Packed; // output pixel format
        stConvertParam.pDstBuffer       = pConvertData;                               // output data buffer
        stConvertParam.nDstBufferSize   = nConvertDataSize;                       // output buffer size
        auto nRet = MV_CC_ConvertPixelType(mHandle, &stConvertParam);
        if (MV_OK != nRet){
            printf("Convert Pixel Type fail! nRet [0x%x]\n", nRet);
            emit sigErrorOccured(mCamConfig.name, CEC_ImgError);
        } else{
            QImage image(pConvertData,imgInfo.nWidth,imgInfo.nHeight, QImage::Format_RGB888);
            emit sigImage(mCamConfig.name, image.copy());
        }
        if(pConvertData){
            free(pConvertData);
            pConvertData = NULL;
        }
    }else{
        QImage image(imgInfo.pData, imgInfo.nWidth, imgInfo.nHeight, imgInfo.nWidth * 1, QImage::Format_Indexed8);
        emit sigImage(mCamConfig.name, image.copy());
    }
}

QStringList CameraHik::enumCameraList()
{
    QStringList camNameList;
    MV_CC_DEVICE_INFO_LIST stDeviceList;
    memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
    auto nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);
    if (MV_OK != nRet){
        printf("Enum Devices fail! nRet [0x%x]\n", nRet);
        return camNameList;
    }

    for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++){
        MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i];
        if (NULL == pDeviceInfo){
            break;
        }
        mTLayerType = pDeviceInfo->nTLayerType;
        if(pDeviceInfo->nTLayerType==MV_GIGE_DEVICE){
            QString cameraName = QString(reinterpret_cast<char*>(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName));
            camNameList << cameraName;
        }else if(pDeviceInfo->nTLayerType==MV_USB_DEVICE){
            QString cameraName = QString(reinterpret_cast<char*>(pDeviceInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName));
            camNameList << cameraName;
        }
    }
    return camNameList;
}
int CameraHik::getPixelFormat()
{
    return getNodeEnum("PixelFormat");
}
bool CameraHik::isColor(int pixelFormat)
{
    switch((MvGvspPixelType)pixelFormat){
    case PixelType_Gvsp_RGB8_Packed:
    case PixelType_Gvsp_BGR8_Packed:
    case PixelType_Gvsp_YUV422_Packed:
    case PixelType_Gvsp_YUV422_YUYV_Packed:
    case PixelType_Gvsp_BayerGR8:
    case PixelType_Gvsp_BayerRG8:
    case PixelType_Gvsp_BayerGB8:
    case PixelType_Gvsp_BayerBG8:
    case PixelType_Gvsp_BayerGB10:
    case PixelType_Gvsp_BayerGB10_Packed:
    case PixelType_Gvsp_BayerBG10:
    case PixelType_Gvsp_BayerBG10_Packed:
    case PixelType_Gvsp_BayerRG10:
    case PixelType_Gvsp_BayerRG10_Packed:
    case PixelType_Gvsp_BayerGR10:
    case PixelType_Gvsp_BayerGR10_Packed:
    case PixelType_Gvsp_BayerGB12:
    case PixelType_Gvsp_BayerGB12_Packed:
    case PixelType_Gvsp_BayerBG12:
    case PixelType_Gvsp_BayerBG12_Packed:
    case PixelType_Gvsp_BayerRG12:
    case PixelType_Gvsp_BayerRG12_Packed:
    case PixelType_Gvsp_BayerGR12:
    case PixelType_Gvsp_BayerGR12_Packed:
        return true;
    case PixelType_Gvsp_Mono8:
    case PixelType_Gvsp_Mono10:
    case PixelType_Gvsp_Mono10_Packed:
    case PixelType_Gvsp_Mono12:
    case PixelType_Gvsp_Mono12_Packed:
        return false;
    default:
        return false;
    }
}

int CameraHik::getScanType()
{
    return getNodeEnum("DeviceScanType");
}

bool CameraHik::isLineScan(int scanType)
{
    return scanType == 1;
}

void CameraHik::setFrameRate(const QString &camName, const float &rate)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeFloat("AcquisitionFrameRate", rate);
}

void CameraHik::setFrameRateControl(const QString &camName, const bool &control)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeBool("AcquisitionFrameRateEnable", control);
}

void CameraHik::setPreDiv(const QString &camName, const int &preDiv)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeInt("PreDivider", preDiv);
}

void CameraHik::setMul(const QString &camName, const int &mul)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeInt("Multiplier", mul);

}

void CameraHik::setPostDiv(const QString &camName, const int &postDiv)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeInt("PostDivider", postDiv);
}

void CameraHik::triggerSoftware()
{
    if(getNodeEnum("TriggerMode") == MV_TRIGGER_MODE_ON
        && getNodeEnum("TriggerSource") == MV_TRIGGER_SOURCE_SOFTWARE){
        execCommand("TriggerSoftware");
    }
}

void CameraHik::setFrameTriggerMode(const QString &camName, const CameraTriggerType &type)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeEnum("TriggerSelector", 6);
    setTriggerMode(camName, type);
}

void CameraHik::setFrameTriggerDelay(const QString &camName, const float &delay)
{
    if(camName != mCamConfig.name)
        return;
    if(!MV_CC_IsDeviceConnected(mHandle))
        return;
    setNodeEnum("TriggerSelector", 6);
    setNodeFloat("TriggerDelay", delay);
}

void CameraHik::setLineTriggerMode(const QString &camName, const CameraTriggerType &type)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeEnum("TriggerSelector", 9);
    setTriggerMode(camName, type);
}


void CameraHik::setTriggerMode(const QString &camName, const CameraTriggerType &type)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    if(type == CTT_Off){
        setNodeEnum("TriggerMode", MV_TRIGGER_MODE_OFF);
    } else {
        setNodeEnum("TriggerMode", MV_TRIGGER_MODE_ON);
        switch (type) {
        case CTT_Software:
            setNodeEnum("TriggerSource",MV_TRIGGER_SOURCE_SOFTWARE);
            break;
        case CTT_FrequencyConverter:
            setNodeEnum("TriggerSource",MV_TRIGGER_SOURCE_FrequencyConverter);
            break;
        case CTT_Line0:
        case CTT_Line1:
        case CTT_Line2:
        case CTT_Line3:
            setNodeEnum("TriggerSource",type - CTT_Line0);
            break;
        default:
            break;
        }
    }
}

void CameraHik::setExposureTime(const QString& camName, const float &value)
{
    if(camName != mCamConfig.name)
        return;
    if(!MV_CC_IsDeviceConnected(mHandle))
        return;
    setNodeFloat("ExposureTime", value);
    saveParamToUserSet();
}

void CameraHik::setGainMode(const QString &camName, const int &gainMode)
{
    if(camName != mCamConfig.name)
        return;
    if(!MV_CC_IsDeviceConnected(mHandle))
        return;
    setNodeEnum("GainAuto", gainMode);
}

void CameraHik::setExposureAutoMode(const QString &camName, const int &expMode)
{
    if(camName != mCamConfig.name)
        return;
    if(!MV_CC_IsDeviceConnected(mHandle))
        return;
    setNodeEnum("ExposureAuto", expMode);
}
void CameraHik::setGain(const QString& camName, const float &gain)
{
    if(camName != mCamConfig.name)
        return;
    if(!MV_CC_IsDeviceConnected(mHandle))
        return;
    setNodeFloat("Gain", gain);
}

void CameraHik::setWhiteBalanceMode(const QString &camName, const int &mode)
{
    if(camName != mCamConfig.name)
        return;
    if(!MV_CC_IsDeviceConnected(mHandle))
        return;
    setNodeEnum("BalanceWhiteAuto", mode);
}

void CameraHik::setWhiteBalanceR(const QString& camName,  const int &value)
{
    if(camName != mCamConfig.name)
        return;
    if(!MV_CC_IsDeviceConnected(mHandle))
        return;
    setNodeEnum("BalanceRatioSelector", 0);
    setNodeInt("BalanceRatio", value);
    saveParamToUserSet();
}

void CameraHik::setWhiteBalanceG(const QString& camName,  const int &value)
{
    if(camName != mCamConfig.name)
        return;
    if(!MV_CC_IsDeviceConnected(mHandle))
        return;
    setNodeEnum("BalanceRatioSelector", 1);
    setNodeInt("BalanceRatio", value);
    saveParamToUserSet();
}

void CameraHik::setWhiteBalanceB(const QString& camName,  const int &value)
{
    if(camName != mCamConfig.name)
        return;
    if(!MV_CC_IsDeviceConnected(mHandle))
        return;
    setNodeEnum("BalanceRatioSelector", 2);
    setNodeInt("BalanceRatio", value);
    saveParamToUserSet();
}
void CameraHik::setWidth(const QString& camName, const int& width)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeInt("Width", width);
}
void CameraHik::setHeight(const QString& camName, const int& height)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeInt("Height", height);
}
void CameraHik::setOffsetX(const QString& camName, const int& off_x)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeInt("OffsetX", off_x);
    saveParamToUserSet();
}
void CameraHik::setOffsetY(const QString& camName, const int& off_y)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus == CS_Unavailable)
        return;
    setNodeInt("OffsetY", off_y);
    saveParamToUserSet();
}

void CameraHik::setReverseX(const QString &camName, const bool &reverse_x)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeBool("ReverseX", reverse_x);
    saveParamToUserSet();
}

void CameraHik::setReverseY(const QString &camName, const bool &reverse_y)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setNodeBool("ReverseY", reverse_y);
    saveParamToUserSet();
}

void CameraHik::setNodeBool(const char* nodeName, bool bValue)
{
    int nRet = MV_CC_SetBoolValue(mHandle, nodeName, bValue);
    if(MV_OK != nRet){
        printf("%s set %s fail! ErrorCode:[0x%x] value:%d\n", mCamConfig.name.toStdString().c_str(), nodeName, nRet, bValue);
    }
}

void CameraHik::setNodeEnum(const char* nodeName, const int& nValue)
{
    int nRet = MV_CC_SetEnumValue(mHandle,nodeName,nValue);
    if(MV_OK != nRet){
        printf("%s set %s fail! ErrorCode:[0x%x] value:%d\n", mCamConfig.name.toStdString().c_str(), nodeName, nRet, nValue);
    }
}

void CameraHik::setNodeInt(const char* nodeName, const int& iValue)
{
    int nRet = MV_CC_SetIntValueEx(mHandle, nodeName, iValue);
    if(MV_OK != nRet){
        printf("%s set %s fail! ErrorCode:[0x%x] value:%d\n", mCamConfig.name.toStdString().c_str(), nodeName, nRet, iValue);
    }
}

void CameraHik::setNodeFloat(const char *nodeName, const float &fValue)
{
    int nRet = MV_CC_SetFloatValue(mHandle, nodeName, fValue);
    if(MV_OK != nRet){
        printf("%s set %s fail! ErrorCode:[0x%x] value:%d\n", mCamConfig.name.toStdString().c_str(), nodeName, nRet, fValue);
    }
}

bool CameraHik::getNodeBool(const char *nodeName)
{
    bool val = false;
    int nRet = MV_CC_GetBoolValue(mHandle, nodeName, &val);
    if(MV_OK != nRet){
        printf("%s get %s fail! ErrorCode:[0x%x]\n", mCamConfig.name.toStdString().c_str(), nodeName, nRet);
    }
    return val;
}

int CameraHik::getNodeEnum(const char *nodeName)
{
    MVCC_ENUMVALUE val;
    int nRet = MV_CC_GetEnumValue(mHandle, nodeName, &val);
    if(MV_OK != nRet){
        printf("%s get %s fail! ErrorCode:[0x%x]\n", mCamConfig.name.toStdString().c_str(), nodeName, nRet);
        val.nCurValue = 0;
    }
    return val.nCurValue;
}

IntValue CameraHik::getNodeInt(const char *nodeName)
{
    IntValue valRe;
    MVCC_INTVALUE val;
    int nRet = MV_CC_GetIntValue(mHandle, nodeName, &val);
    if(MV_OK != nRet){
        printf("%s get %s fail! ErrorCode:[0x%x]\n", mCamConfig.name.toStdString().c_str(), nodeName, nRet);
        val.nCurValue = 0;
    }
    valRe.val = val.nCurValue;
    valRe.min = val.nMin;
    valRe.max = val.nMax;
    valRe.inc = val.nInc;
    return valRe;
}

FloatValue CameraHik::getNodeFloat(const char *nodeName)
{
    FloatValue valRe;
    MVCC_FLOATVALUE val;
    int nRet = MV_CC_GetFloatValue(mHandle, nodeName, &val);
    if(MV_OK != nRet){
        printf("%s get %s fail! ErrorCode:[0x%x]\n", mCamConfig.name.toStdString().c_str(), nodeName, nRet);
    }
    valRe.val = val.fCurValue;
    valRe.min = val.fMin;
    valRe.max = val.fMax;
    return valRe;
}

void CameraHik::execCommand(const char *nodeName)
{
    int nRet = MV_CC_SetCommandValue(mHandle, nodeName);
    if(MV_OK != nRet){
        printf("%s command %s fail! ErrorCode:[0x%x]\n", mCamConfig.name.toStdString().c_str(), nodeName, nRet);
    }
}

CameraTriggerType CameraHik::getFrameTriggerMode(const QString& camName)
{
    if(camName != mCamConfig.name)
        return CTT_Off;
    setNodeEnum("TriggerSelector", 6);
    int mode = getNodeEnum("TriggerMode");
    int source = getNodeEnum("TriggerSource");
    return getTriggerMode(mode, source);;
}
FloatValue CameraHik::getFrameTriggerDelay(const QString& camName)
{
    setNodeEnum("TriggerSelector", 6);
    FloatValue delay = getNodeFloat("TriggerDelay");
    return delay;
}
CameraTriggerType CameraHik::getLineTriggerMode(const QString& camName)
{
    setNodeEnum("TriggerSelector", 9);
    int mode = getNodeEnum("TriggerMode");
    int source = getNodeEnum("TriggerSource");
    return getTriggerMode(mode, source);
}

CameraTriggerType CameraHik::getTriggerMode(const int &mode, const int& source)
{
    CameraTriggerType trigMode;
    if(mode == MV_TRIGGER_MODE_OFF){
        trigMode = CTT_Off;
    } else {
        switch (source) {
        case MV_TRIGGER_SOURCE_SOFTWARE:
            trigMode = CTT_Software;
            break;
        case MV_TRIGGER_SOURCE_FrequencyConverter:
            trigMode = CTT_FrequencyConverter;
            break;
        case MV_TRIGGER_SOURCE_LINE0:
        case MV_TRIGGER_SOURCE_LINE1:
        case MV_TRIGGER_SOURCE_LINE2:
        case MV_TRIGGER_SOURCE_LINE3:
            trigMode = CameraTriggerType(source + CTT_Line0);
            break;
        default:
            trigMode = CTT_Off;
            break;
        }
    }
    return trigMode;
}

IntValue CameraHik::getWidth(const QString& camName)
{
    return getNodeInt("Width");
}
IntValue CameraHik::getHeight(const QString& camName)
{
    return getNodeInt("Height");
}
IntValue CameraHik::getOffsetX(const QString& camName)
{
    return getNodeInt("OffsetX");
}
IntValue CameraHik::getOffsetY(const QString& camName)
{
    return getNodeInt("OffsetY");
}
bool CameraHik::getReverseX(const QString& camName)
{
    return getNodeBool("ReverseX");
}
bool CameraHik::getReverseY(const QString& camName)
{
    return getNodeBool("ReverseY");
}
int CameraHik::getWhiteBalanceMode(const QString& camName)
{
    return getNodeEnum("BalanceWhiteAuto");
}
IntValue CameraHik::getWhiteBalanceR(const QString& camName)
{
    setNodeEnum("BalanceRatioSelector", 0);
    return getNodeInt("BalanceRatio");

}
IntValue CameraHik::getWhiteBalanceG(const QString& camName)
{
    setNodeEnum("BalanceRatioSelector", 1);
    return getNodeInt("BalanceRatio");
}
IntValue CameraHik::getWhiteBalanceB(const QString& camName)
{
    setNodeEnum("BalanceRatioSelector", 2);
    return getNodeInt("BalanceRatio");
}
int CameraHik::getExposureAutoMode(const QString& camName)
{
    return  getNodeEnum("ExposureAuto");
    if(!mCamConfig.isLine){
    }
}
FloatValue CameraHik::getExposureTime(const QString& camName)
{
    return getNodeFloat("ExposureTime");
}
int CameraHik::getGainMode(const QString& camName)
{
    return getNodeEnum("GainAuto");
}
FloatValue CameraHik::getGain(const QString& camName)
{
    return getNodeFloat("Gain");
}
bool CameraHik::getFrameRateControl(const QString& camName)
{
    return getNodeBool("AcquisitionFrameRateEnable");

}
FloatValue CameraHik::getFrameRate(const QString& camName)
{
    FloatValue rate = getNodeFloat("AcquisitionFrameRate");
    FloatValue rateMax = getNodeFloat("ResultingFrameRate");

    FloatValue value;
    value.val = rate.val;
    value.max = rateMax.val;
    return value;
}

IntValue CameraHik::getPreDiv(const QString &camName)
{
    return getNodeInt("PreDivider");
}

IntValue CameraHik::getMul(const QString &camName)
{
    return getNodeInt("Multiplier");
}

IntValue CameraHik::getPostDiv(const QString &camName)
{
    return getNodeInt("PostDivider");
}

